﻿#include "ImageScaler.h"

ImageScaler::ImageScaler()
{
    sws_ctx_ = NULL;
    src_pix_fmt_ = AV_PIX_FMT_NONE;
    dst_pix_fmt_ = AV_PIX_FMT_NONE;

    src_width_ = src_height_ = 0;
    dst_width_ = dst_height_ = 0;
}

ImageScaler::~ImageScaler()
{
    DeInit();
}

int ImageScaler::Init(uint32_t src_width, uint32_t src_height, int src_pix_fmt,uint32_t dst_width, uint32_t dst_height, int dst_pix_fmt)
{
    src_width_ = src_width;
    src_height_ = src_height;
    src_pix_fmt_ = (AVPixelFormat)src_pix_fmt;
    dst_width_ = dst_width;
    dst_height_ = dst_height;
    dst_pix_fmt_ = (AVPixelFormat)dst_pix_fmt;
    //创建软件缩放器SWS，WS部分是指FFmpeg的视频图像处理库libswscale
    sws_ctx_ = sws_getContext(
                src_width_,
                src_height_,
                (AVPixelFormat)src_pix_fmt_,
                dst_width_,
                dst_height_,
                (AVPixelFormat)dst_pix_fmt_,
                SWS_FAST_BILINEAR,
                NULL,
                NULL,
                NULL);
    if (!sws_ctx_)
        return -1;
    return 0;
}

void ImageScaler::DeInit()
{
    if(sws_ctx_)
    {
        sws_freeContext(sws_ctx_);
        sws_ctx_ = NULL;
    }
}

int ImageScaler::Scale(const AVFrame *src_frame, AVFrame *dst_frame)
{
    if(src_frame->width != src_width_
            || src_frame->height != src_height_
            || src_frame->format != src_pix_fmt_
            || dst_frame->width != dst_width_
            || dst_frame->height != dst_height_
            || dst_frame->format != dst_pix_fmt_
            || !sws_ctx_){
        // 重新初始化
        DeInit();
        int ret = Init(src_frame->width, src_frame->height, src_frame->format,
                            dst_frame->width, dst_frame->height, dst_frame->format);
        if(ret != 0)
            return ret;
    }

    int dst_slice_h = sws_scale(sws_ctx_, (const uint8_t **) src_frame->data, src_frame->linesize, 0, src_frame->height,
                                dst_frame->data, dst_frame->linesize);
    if(dst_slice_h>0)
        return 0;
    else
        return -1;
}

int ImageScaler::Scale2(const VideoFrame *src_frame, VideoFrame *dst_frame)
{
    if(src_frame->width != src_width_
            || src_frame->height != src_height_
            || src_frame->format != src_pix_fmt_
            || dst_frame->width != dst_width_
            || dst_frame->height != dst_height_
            || dst_frame->format != dst_pix_fmt_
            || !sws_ctx_) {
        DeInit();
        int ret = Init(src_frame->width, src_frame->height, src_frame->format,
                            dst_frame->width, dst_frame->height, dst_frame->format);
        if(ret != 0)
            return ret;
    }
    int dst_slice_h = sws_scale(sws_ctx_,
                                (const uint8_t **)src_frame->data,
                                src_frame->linesize,
                                0,  // 起始位置
                                src_frame->height, //处理多少行
                                dst_frame->data,
                                dst_frame->linesize);
    if(dst_slice_h>0)
        return 0;
    else
        return -1;
}

int ImageScaler::Scale3(const Frame *src_frame, VideoFrame *dst_frame)
{
    if(src_frame->width != src_width_
            || src_frame->height != src_height_
            || src_frame->format != src_pix_fmt_
            || dst_frame->width != dst_width_
            || dst_frame->height != dst_height_
            || dst_frame->format != dst_pix_fmt_
            || !sws_ctx_) {
        DeInit();
        int ret = Init(src_frame->width, src_frame->height, src_frame->format,
                            dst_frame->width, dst_frame->height, dst_frame->format);
        if(ret != 0)
            return ret;
    }
    int dst_slice_h = sws_scale(sws_ctx_,
                                (const uint8_t **)src_frame->frame->data,
                                src_frame->frame->linesize,
                                0,  // 起始位置
                                src_frame->height, //处理多少行
                                dst_frame->data,
                                dst_frame->linesize);
    if(dst_slice_h>0)
        return 0;
    else
        return -1;
}
